package com.medusa.aps.business.modules.plan.mp.service.impl;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.QueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.medusa.aps.business.model.pagination.Page;
import com.medusa.aps.business.modules.plan.model.input.GanttPageParm;
import com.medusa.aps.business.modules.plan.model.output.GanttChartListModel;
import com.medusa.aps.business.modules.plan.model.output.GanttChartVo;
import com.medusa.aps.business.modules.plan.model.output.PageListModel;
import com.medusa.aps.business.modules.plan.mp.entity.GanttChartequipment;
import com.medusa.aps.business.modules.plan.mp.entity.ProcessDetails;
import com.medusa.aps.business.modules.plan.mp.mapper.GanttChartequipmentMapper;
import com.medusa.aps.business.modules.plan.mp.service.GanttChartequipmentService;
import com.medusa.aps.business.modules.plan.mp.service.ProcessDetailsService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 甘特图-设备服务实现类
 *
 * @author yuxh
 * @since 2023-08-14 17:37:45
 */
@Service("ganttChartequipmentService")
public class GanttChartequipmentServiceImpl extends ServiceImpl<GanttChartequipmentMapper, GanttChartequipment> implements GanttChartequipmentService {


    @Resource
    private ProcessDetailsService processDetailsService;

    @Override
    public GanttChartVo selectGattList(GanttPageParm param) {
        //分页查询设备信息
        LocalDate now = LocalDate.now();
        QueryChainWrapper<ProcessDetails> query = processDetailsService.query()
                .select()
                .select("equipment_id AS equipmentId",
                        "ANY_VALUE(equipment_code) AS equipmentCode",
                        "ANY_VALUE(equipment_name) AS equipmentName",
                        "ANY_VALUE(workshop_name) AS workshopName",
                        "ANY_VALUE(create_time) AS createTime")
                .groupBy("equipment_id")
                .like(StrUtil.isNotBlank(param.getDeviceName()), "equipment_name", param.getDeviceName())
                .like(StrUtil.isNotBlank(param.getWorkshopName()), "workshop_name", param.getWorkshopName())
                .ge(param.getPlanTime().getStartTime() != null, "planned_start_time", param.getPlanTime().getStartTime())
                .ge(param.getPlanTime().getStartTime() == null, "planned_start_time", now);
        if (param.getPlanTime().getEndTime() != null) {
            query.le("planned_end_time", param.getPlanTime().getEndTime());
        }
        Page<ProcessDetails> devicePage = query.orderByDesc("createTime")
                .page(new Page<>(param.getCurrent(), param.getSize()));
        GanttChartVo ganttChart = new GanttChartVo();
        List<ProcessDetails> records = devicePage.getRecords();
        if (CollUtil.isEmpty(records)) {
            return ganttChart;
        }
        //根据设备查询结果查询工序明细
        Set<Long> equipmentIds = records.stream().map(ProcessDetails::getEquipmentId).collect(Collectors.toSet());
        LambdaQueryChainWrapper<ProcessDetails> lambdaQuery = processDetailsService.lambdaQuery()
                .select(ProcessDetails::getId,
                        ProcessDetails::getProcessNumber,
                        ProcessDetails::getProcessName,
                        ProcessDetails::getOrderNumber,
                        ProcessDetails::getEquipmentId,
                        ProcessDetails::getPlannedStartTime,
                        ProcessDetails::getPlannedEndTime,
                        ProcessDetails::getMaterialCode,
                        ProcessDetails::getMaterialName,
                        ProcessDetails::getPlannedQuantity
                )
                .in(ProcessDetails::getEquipmentId, equipmentIds)
                .like(StrUtil.isNotBlank(param.getDeviceName()), ProcessDetails::getEquipmentName, param.getDeviceName())
                .like(StrUtil.isNotBlank(param.getWorkshopName()), ProcessDetails::getWorkshopName, param.getWorkshopName())
                .ge(param.getPlanTime().getStartTime() != null, ProcessDetails::getPlannedStartTime, param.getPlanTime().getStartTime())
                .ge(param.getPlanTime().getStartTime() == null, ProcessDetails::getPlannedStartTime, now);
        if (param.getPlanTime().getEndTime() != null) {
            lambdaQuery.le(ProcessDetails::getPlannedEndTime, param.getPlanTime().getEndTime());
        }
        List<ProcessDetails> details = lambdaQuery.list();
        //根据设备 id 分组
        Map<Long, List<ProcessDetails>> deviceProcessMap = details.stream()
                .collect(Collectors.groupingBy(ProcessDetails::getEquipmentId));

        return ganttChart
                .setGanttDatas(
                        devicePage.convert(record -> {
                                    Long equipmentId = record.getEquipmentId();
                                    List<ProcessDetails> currentDetails = CollUtil.emptyIfNull(deviceProcessMap.get(equipmentId));
                                    return new PageListModel()
                                            .setDeviceId(equipmentId)
                                            .setDeviceCode(record.getEquipmentCode())
                                            .setDeviceName(record.getEquipmentName())
                                            .setWorkshopName(record.getWorkshopName())
                                            .setNumberOfTasks(currentDetails.size())
                                            .setGanttList(
                                                    currentDetails.stream()
                                                            .map(
                                                                    detail -> new GanttChartListModel()
                                                                            .setProcessDetailsId(detail.getId())
                                                                            .setProcessNumber(detail.getProcessNumber())
                                                                            .setProcessName(detail.getProcessName())
                                                                            .setOrderNumber(detail.getOrderNumber())
                                                                            .setPlanStartTime(detail.getPlannedStartTime())
                                                                            .setPlanEndTime(detail.getPlannedEndTime())
                                                                            .setMaterialCode(detail.getMaterialCode())
                                                                            .setMaterialName(detail.getMaterialName())
                                                                            .setQuantity(detail.getPlannedQuantity().intValue())
                                                            )
                                                            .sorted(Comparator.comparing(GanttChartListModel::getPlanStartTime))
                                                            .toList()
                                            );
                                }
                        )
                ).planDateRange();
    }
}

